package com.x2.modular.export.action;

import com.x2.base.pojo.page.LayuiPageInfo;
import com.x2.modular.export.kit.DataDao;
import com.x2.modular.export.kit.DataUtil;
import com.x2.modular.export.util.ExcelBuilder;
import com.x2.modular.export.vo.*;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class XyExportRun0 implements XyExportRun<XyExportVO> {
    private int rowIndex;
    private LayuiPageInfo pageInfo;
    private XyExcelDefVO defVO;
    private ExcelBuilder builder;
    private List<XyExportExcelItem> itemDisList = new ArrayList<>();

    /**
     * 初始化
     *
     * @param inData
     * @param inDefVO
     */
    public XyExportRun0(LayuiPageInfo inData, XyExcelDefVO inDefVO) {
        this.pageInfo = inData;
        this.defVO = inDefVO;
    }

    /**
     * 运行
     *
     * @return
     * @throws Exception
     */
    public XyExportVO call() throws Exception {
        try {
            //构造加过
            builder = new ExcelBuilder();
            builder.openFile("数据");
            //excel表头
            buildTitle(builder);
            //数据查询
            DataDao dao = new DataDao(this.pageInfo, defVO, itemDisList);
            //清理一下大数据无用对象
            this.pageInfo.setData(null);
            this.pageInfo = null;
            //数据部分
            fillData(builder, dao);
            byte[] data = builder.toByte();
            XyExportVO resVO = new XyExportVO();
            resVO.setFileTitle(defVO.getFileTitle());
            resVO.setFileData(data);
            return resVO;
        } catch (Exception ex) {
            ex.printStackTrace();
            throw ex;
        } finally {
            System.gc();
        }

    }


    /**
     * 构建表体
     *
     * @param builder
     * @throws Exception
     */
    private void fillData(ExcelBuilder builder, DataDao dao) throws Exception {

        Map<String, Object> data;
        XSSFRow row;
        XSSFCell cell;
        List<Map<String, Object>> dataList;

        for (String pk : dao.getBillPkList()) {

            dataList = dao.getBill(pk);
            for (int index2 = 0; index2 < dataList.size(); index2++) {
                data = dataList.get(index2);
                row = builder.getRow(rowIndex++, 20);
                Object value;
                int colIndex = 0;

                for (XyExportExcelItem item : itemDisList) {
                    //取得单元格
                    cell = getCell(row, item, colIndex++);
                    //赋值
                    setCellValue(item, cell, data.get(item.getCode()));
                }
            }
            int bodySize = dataList.size();
            if (bodySize > 1 && "Y".equalsIgnoreCase(defVO.getBody().getMergeMain())) {
                for (int ii = 0; ii < itemDisList.size(); ii++) {
                    if (itemDisList.get(ii).isMainItem()) {
                        builder.mergeCell(rowIndex - bodySize, rowIndex - 1, ii, ii);
                    }
                }
            }
        }
    }

    /**
     * 取得单元格
     *
     * @param row
     * @param dataItem
     * @param colIndex
     * @return
     * @throws Exception
     */
    private XSSFCell getCell(XSSFRow row, XyExportExcelItem dataItem, int colIndex) throws Exception {
        XSSFCell cell = null;
        if (dataItem.getAlign() != null) {
            if ("left".equalsIgnoreCase(dataItem.getAlign())) {
                cell = builder.getCellLeft(row, colIndex);
            } else if ("right".equalsIgnoreCase(dataItem.getAlign())) {
                cell = builder.getCellRight(row, colIndex);
            } else {
                cell = builder.getCell(row, colIndex);
            }
        } else {
            cell = builder.getCell(row, colIndex);
        }
        return cell;
    }

    /**
     * 赋值
     *
     * @param dataItem
     * @param cell
     * @param value
     * @throws Exception
     */
    private void setCellValue(XyExportExcelItem dataItem, XSSFCell cell, Object value) throws Exception {
        DataUtil.setCellValue(this.builder, cell, dataItem, value);
    }


    /**
     * 构建表头
     *
     * @param builder
     * @throws Exception
     */
    private void buildTitle(ExcelBuilder builder) throws Exception {
        rowIndex = 0;
        int colIndex = 0;
        XSSFRow row;
        //表格
        List<XyExportExcelRow> rowTitles = buildHeadRow();
        XyExportExcelItem item;
        int colSize = rowTitles.get(0).getItemList().size();
        for (XyExportExcelRow rowTitle : rowTitles) {
            row = builder.getRow(rowIndex++, 20);
            for (colIndex = 0; colIndex < colSize; colIndex++) {
                if (rowTitle.getItemList().size() > colIndex) {
                    item = rowTitle.getItemList().get(colIndex);
                    builder.getCell(row, colIndex).setCellValue(item.getName());
                    if (item.getWidth() != null && item.getWidth() > 1) {
                        int width = item.getWidthInExcel().intValue();
                        if (width > 100) {
                            width = 100;
                        }
                        builder.setColumnWidth(colIndex, width);
                    }
                } else {
                    builder.getCell(row, colIndex).setCellValue("");
                }
            }
        }

        //合并
        int rowSize = rowTitles.size();
        int columnSize = rowTitles.get(0).getItemList().size();
        for (int r = 0; r < rowSize; r++) {
            for (int c = 0; c < columnSize; c++) {
                item = rowTitles.get(r).getItemList().get(c);
                if (item.getRowspan() >= 1 && item.getColspan() >= 1 && item.getRowspan() + item.getColspan() > 2) {
                    builder.mergeCell(r, r + item.getRowspan() - 1, c, c + item.getColspan() - 1);
                }
            }
        }
        //数据列
        if (defVO.getTitle().getDataIndex() >= 0) {
            itemDisList.addAll(rowTitles.get(defVO.getTitle().getDataIndex()).getItemList());
        } else {
            itemDisList.addAll(rowTitles.get(rowSize - 1).getItemList());
        }
    }


    /**
     * 构建table
     *
     * @return
     */
    public List<XyExportExcelRow> buildHeadRow() {
        XyExportExcelTitle title = defVO.getTitle();
        List<XyExportExcelRow> rowList = new ArrayList<>();

        //列全显示
        XyExportExcelRow row;
        XyExportExcelItem itemTemp;
        XyExportExcelItem item;
        for (int nowRowIndex = 0; nowRowIndex < title.getRowList().size(); nowRowIndex++) {
            row = title.getRowList().get(nowRowIndex).clone();
            List<XyExportExcelItem> itemList = new ArrayList<>();
            for (int nowColIndex = 0; nowColIndex < row.getItemList().size(); nowColIndex++) {
                item = row.getItemList().get(nowColIndex);
                for (int clspanIndex = 0; clspanIndex < item.getColspan(); clspanIndex++) {
                    itemTemp = item.clone();
                    itemTemp.setColspan(1);
                    itemList.add(itemTemp);
                }
            }
            row.setItemList(itemList);
            rowList.add(row);
        }
        //行对齐
        for (int nowRowIndex = 0; nowRowIndex < rowList.size(); nowRowIndex++) {
            row = rowList.get(nowRowIndex);
            for (int nowColIndex = 0; nowColIndex < row.getItemList().size(); nowColIndex++) {
                item = row.getItemList().get(nowColIndex);
                for (int rowspanIndex = 1; rowspanIndex < item.getRowspan(); rowspanIndex++) {
                    itemTemp = item.clone();
                    itemTemp.setRowspan(1);
                    rowList.get(nowRowIndex + rowspanIndex).getItemList().add(nowColIndex, itemTemp);
                }
            }
        }
        XyExportExcelRow targetRow = rowList.get(defVO.getTitle().getTitleIndex());
        List<String> selectdList = new ArrayList<>(defVO.getMainItems());
        selectdList.addAll(defVO.getBodyItems());

        //清除未选择项目
        List<Integer> deleteColumnIdx = new ArrayList<>();
        XyExportExcelItem targetItem;
        for (int nowColIndex = 0; nowColIndex < targetRow.getItemList().size(); nowColIndex++) {
            targetItem = targetRow.getItemList().get(nowColIndex);
            if (selectdList.contains(targetItem.getCode())) {
                continue;
            }
            deleteColumnIdx.add(nowColIndex);
        }
        for (XyExportExcelRow rowDel : rowList) {
            List<XyExportExcelItem> itemList = new ArrayList<>();
            for (int delInx = 0; delInx < rowDel.getItemList().size(); delInx++) {
                if (!deleteColumnIdx.contains(delInx)) {
                    itemList.add(rowDel.getItemList().get(delInx));
                }
            }
            rowDel.setItemList(itemList);
        }
        //合并单元格
        List<XyExportExcelRow> rowTitles = rowList;
        //行列表
        int rowSize = rowTitles.size();
        int columnSize = rowTitles.get(0).getItemList().size();
        XyExportExcelItem nextItem;
        for (int r = 0; r < rowSize; r++) {
            for (int c = 0; c < columnSize; ) {
                item = rowTitles.get(r).getItemList().get(c);
                int end = c + 1;
                while (end < columnSize) {
                    nextItem = rowTitles.get(r).getItemList().get(end);
                    if (!nextItem.getCode().equals(item.getCode())) {
                        break;
                    }
                    nextItem.setColspan(1);
                    end++;
                }
                item.setColspan(end - c);
                c = end;
            }
        }
        for (int r = 0; r < rowSize; r++) {
            for (int c = 0; c < columnSize; c++) {
                item = rowTitles.get(r).getItemList().get(c);
                if (item.getRowspan() <= 1) {
                    continue;
                }
                int end = r + 1;
                while (end < rowSize) {
                    nextItem = rowTitles.get(end).getItemList().get(c);
                    if (!nextItem.getCode().equals(item.getCode())) {
                        break;
                    }
                    nextItem.setRowspan(1);
                    end++;
                }
                item.setRowspan(end - r);
            }
        }

        return rowList;
    }


}
